use super::*;
use lexer::*;

// ## 2. Syntax
// ### 2.a. Comments
// ### 2.b. White space
// ### 2.c. Keywords
// ### 2.d. Special characters

// ## 2.e. Numbers and other metrics
// #### 2.e.i. Number
#[derive(Debug, Clone)]
pub struct Number(pub String);
impl From<&str> for Number {
	fn from(value: &str) -> Self {
		Self(value.into())
	}
}

// #### 2.e.ii. Metric
pub type Metric = Number;

// #### 2.e.iii. Device table
#[derive(Debug, Clone, Default)]
pub struct Device(pub Vec<(Number, Number)>);
impl Device {
	pub fn parse(r: &mut Lexer<'_>) -> Result<Self, Error> {
		r.expect(Event::DeviceKw)?;
		let mut this = Self::default();
		loop {
			match r.read_next()? {
				Event::RAngle => break,
				Event::Number(v0) => {
					let v1 = r.expect_number()?;
					this.0.push((v0.into(), v1.into()));
				}
				Event::Comma => {}
				Event::NullKw => {
					r.expect(Event::RAngle)?;
					debug_assert!(this.0.is_empty());
					break;
				}
				e => return Err(Error::Unexpect(format!("{:?}", e))),
			}
		}
		Ok(this)
	}
}

// #### 2.e.iv. Value record
#[derive(Debug, Clone)]
pub enum ValueRecord {
	Metric(Metric),
	Null,
	Ref(String),
	M4(Metric, Metric, Metric, Metric),
	M4D4(Metric, Metric, Metric, Metric, Device, Device, Device, Device),
}
impl ValueRecord {
	pub fn parse(r: &mut Lexer<'_>) -> Result<Self, Error> {
		match r.read_next()? {
			Event::Number(v) => Ok(Self::Metric(v.into())), // format A
			Event::LAngle => Self::parse_value(r),
			e => Err(Error::Unexpect(format!("{:?}", e))),
		}
	}
	pub fn parse_value(r: &mut Lexer<'_>) -> Result<Self, Error> {
		match r.read_next()? {
			Event::Number(v0) => match r.read_next()? {
				// Event::RAngle => Ok(Self), // format A
				Event::Number(v1) => {
					let v2 = r.expect_number()?;
					let v3 = r.expect_number()?;
					match r.read_next()? {
						Event::RAngle => Ok(Self::M4(v0.into(), v1.into(), v2.into(), v3.into())), // format B
						Event::LAngle => {
							let d0 = Device::parse(r)?;
							r.expect(Event::LAngle)?;
							let d1 = Device::parse(r)?;
							r.expect(Event::LAngle)?;
							let d2 = Device::parse(r)?;
							r.expect(Event::LAngle)?;
							let d3 = Device::parse(r)?;
							r.expect(Event::RAngle)?;
							Ok(Self::M4D4(
								v0.into(),
								v1.into(),
								v2.into(),
								v3.into(),
								d0.into(),
								d1.into(),
								d2.into(),
								d3.into(),
							)) // format C
						}
						e => Err(Error::Unexpect(format!("{:?}", e))),
					}
				}
				e => Err(Error::Unexpect(format!("{:?}", e))),
			},
			Event::NullKw => {
				r.expect(Event::RAngle)?;
				Ok(Self::Null) // format D
			}
			Event::Ident(v) => {
				r.expect(Event::RAngle)?;
				Ok(Self::Ref(v.into()))
			} // format E
			e => Err(Error::Unexpect(format!("{:?}", e))),
		}
	}
}

// #### 2.e.v. Named value record
#[derive(Debug, Clone)]
pub struct ValueRecordDef {
	pub name: String,
	pub value: ValueRecord,
}
impl ValueRecordDef {
	pub fn parse(r: &mut Lexer<'_>) -> Result<Self, Error> {
		let value = ValueRecord::parse(r)?;
		let name = r.expect_ident()?;
		r.expect(Event::Semi)?;
		Ok(Self {
			name: name.to_string(),
			value,
		})
	}
}

// #### 2.e.vi. Contour point
#[derive(Debug, Clone)]
pub struct ContourPoint(pub Number);
impl ContourPoint {
	pub fn parse(r: &mut Lexer<'_>) -> Result<Self, Error> {
		match r.read_next()? {
			Event::Number(v) => Ok(Self(v.into())),
			e => Err(Error::Unexpect(format!("{:?}", e))),
		}
	}
}

// #### 2.e.vii. Anchor
#[derive(Debug, Clone)]
pub enum Anchor {
	Null,
	Ref(String),
	M2(Metric, Metric),
	M2CP(Metric, Metric, ContourPoint),
	M2D2(Metric, Metric, Device, Device),
}
impl Anchor {
	pub fn parse(r: &mut Lexer<'_>) -> Result<Self, Error> {
		r.expect(Event::AnchorKw)?;
		match r.read_next()? {
			Event::Number(v0) => {
				let v1 = r.expect_number()?;
				match r.read_next()? {
					Event::RAngle => Ok(Self::M2(v0.into(), v1.into())), // format A
					Event::ContourpointKw => {
						let cp = ContourPoint::parse(r)?;
						r.expect(Event::RAngle)?;
						Ok(Self::M2CP(v0.into(), v1.into(), cp)) // fromat B
					}
					Event::LAngle => {
						let d0 = Device::parse(r)?;
						r.expect(Event::LAngle)?;
						let d1 = Device::parse(r)?;
						r.expect(Event::RAngle)?;
						Ok(Self::M2D2(v0.into(), v1.into(), d0.into(), d1.into())) // format C
					}
					e => Err(Error::Unexpect(format!("{:?}", e))),
				}
			}
			Event::NullKw => {
				r.expect(Event::RAngle)?;
				Ok(Self::Null) // format D
			}
			Event::Ident(v) => {
				r.expect(Event::RAngle)?;
				Ok(Self::Ref(v.into())) // format E
			}
			e => Err(Error::Unexpect(format!("{:?}", e))),
		}
	}
}

//#### 2.e.viii. Named anchor definition
#[derive(Debug, Clone)]
pub struct AnchorDef {
	pub name: String,
	pub value: Anchor,
}
impl AnchorDef {
	pub fn parse(r: &mut Lexer<'_>) -> Result<Self, Error> {
		match r.read_next()? {
			Event::Number(v0) => {
				let v1 = r.expect_number()?;
				match r.read_next()? {
					Event::Ident(name) => {
						r.expect(Event::Semi)?;
						Ok(Self {
							name: name.into(),
							value: Anchor::M2(v0.into(), v1.into()),
						}) // format A
					}
					Event::ContourpointKw => {
						let cp = ContourPoint::parse(r)?;
						let name = r.expect_ident()?;
						r.expect(Event::Semi)?;
						Ok(Self {
							name: name.into(),
							value: Anchor::M2CP(v0.into(), v1.into(), cp),
						}) // format B
					}
					e => Err(Error::Unexpect(format!("{:?}", e))),
				}
			}
			e => Err(Error::Unexpect(format!("{:?}", e))),
		}
	}
}

// ### 2.f. Glyphs
// #### 2.f.i. Glyph name
// #### 2.f.ii. CID

// ### 2.g. Glyph classes
#[derive(Debug, Clone, Default)]
pub struct Class(pub Vec<ClassItem>);
impl Class {
	pub fn parse(r: &mut Lexer<'_>) -> Result<Self, Error> {
		let mut this = Self::default();
		loop {
			match r.read_next()? {
				Event::RSquare => break,
				// #### 2.g.i. Ranges
				Event::Hyphen => {
					let last = this.0.pop().ok_or(Error::Msg("expect single item before hyphen"))?;
					match last {
						ClassItem::Glyph(start) => match r.read_next()? {
							Event::Ident(end) => this.0.push(ClassItem::Glyphs(start, end.into())),
							e => return Err(Error::Unexpect(format!("{:?}", e))),
						},
						_ => return Err(Error::Msg("expect single item before hyphen")),
					}
				}
				Event::Ident(v) => this.0.push(ClassItem::Glyph(v.into())),
				Event::Group(v) => this.0.push(ClassItem::Ref(v.into())),
				e => return Err(Error::Unexpect(format!("{:?}", e))),
			}
		}
		Ok(this)
	}
	pub fn is_null(&self) -> bool {
		self.0.is_empty()
	}
	pub fn is_single(&self) -> bool {
		self.0.len() == 1
			&& match self.0.get(0) {
				Some(ClassItem::Glyph(_)) => true,
				_ => false,
			}
	}
	pub fn is_class(&self) -> bool {
		self.0.len() > 1
			|| match self.0.get(0) {
				None => false,
				Some(ClassItem::Glyph(_)) => false,
				_ => true,
			}
	}
}
#[derive(Debug, Clone)]
pub enum ClassItem {
	Ref(String),
	Glyph(String),
	Glyphs(String, String),
}

// #### 2.g.ii. Named glyph classes
#[derive(Debug, Clone)]
pub struct ClassDef {
	pub name: String,
	pub value: Class,
}
impl ClassDef {
	pub fn parse(r: &mut Lexer<'_>, name: &str) -> Result<Self, Error> {
		r.expect(Event::Eq)?;
		let this = match r.read_next()? {
			Event::LSquare => {
				let value = Class::parse(r)?;
				Self { name: name.into(), value }
			}
			Event::Group(v) => {
				// link
				Self {
					name: name.into(),
					value: Class(vec![ClassItem::Ref(v.into())]),
				}
			}
			e => return Err(Error::Unexpect(format!("{:?}", e))),
		};
		r.expect(Event::Semi)?;
		Ok(this)
	}
}

// ### 2.h. Tags
#[derive(Debug, Clone, PartialEq)]
pub struct Tag(pub std::borrow::Cow<'static, str>);
impl TryFrom<&str> for Tag {
	type Error = Error;
	fn try_from(value: &str) -> Result<Self, Self::Error> {
		if value.len() > 4 {
			return Err(Error::Msg("tag len > 4"));
		}
		Ok(Self(std::borrow::Cow::Owned(value.into())))
	}
}
impl Tag {
	pub const SCRIPT_DEFT: Self = Self(std::borrow::Cow::Borrowed("DEFT"));
	pub const LANGUAGE_DEFT: Self = Self(std::borrow::Cow::Borrowed("deft"));
	pub const AALT: Self = Self(std::borrow::Cow::Borrowed("aalt"));
	pub const SIZE: Self = Self(std::borrow::Cow::Borrowed("size"));
	pub fn is_stylistic_set(&self) -> bool {
		self.0.starts_with("ss")
	}
	pub fn is_character_variant(&self) -> bool {
		self.0.starts_with("cv")
	}
}

#[cfg(test)]
mod tests {
	use super::*;
	#[test]
	fn value_record() {
		_ = ValueRecord::parse(&mut Lexer::new("-3")).unwrap();
		_ = ValueRecord::parse(&mut Lexer::new("<-80 0 -160 0>")).unwrap();
		let content = "<1 2 3 4 <device 8 88> <device 11 111, 12 112> <device NULL> <device 33 -113, 44 -114, 55 115>>";
		_ = ValueRecord::parse(&mut Lexer::new(content)).unwrap();
		_ = ValueRecord::parse(&mut Lexer::new("<NULL>")).unwrap();
		_ = ValueRecord::parse(&mut Lexer::new("<KERN_POS_1>")).unwrap();
	}
	#[test]
	fn value_record_def() {
		_ = Fea::parse("", &mut Lexer::new("valueRecordDef 123 format_a;")).unwrap();
		_ = Fea::parse("", &mut Lexer::new("valueRecordDef <1 2 3 4> format_b;")).unwrap();
		let content =
			"valueRecordDef <1 2 3 4 <device 8 88> <device 11 111, 12 112> <device NULL> <device 33 -113, 44 -114, 55 115>> format_c;";
		_ = Fea::parse("", &mut Lexer::new(content)).unwrap();
		_ = Fea::parse("", &mut Lexer::new("valueRecordDef <NULL> format_d;")).unwrap();
		_ = Fea::parse("", &mut Lexer::new("valueRecordDef <KERN_POS_1> format_e;")).unwrap();
	}
	#[test]
	fn anchor() {
		_ = Anchor::parse(&mut Lexer::new("anchor 120 -20>")).unwrap();
		_ = Anchor::parse(&mut Lexer::new("anchor 120 -20 contourpoint 5>")).unwrap();
		_ = Anchor::parse(&mut Lexer::new("anchor 120 -20 <device 11 1> <device NULL>>")).unwrap();
		_ = Anchor::parse(&mut Lexer::new("anchor NULL>")).unwrap();
		_ = Anchor::parse(&mut Lexer::new("anchor TOP_ANCHOR_E>")).unwrap();
	}
	#[test]
	fn anchor_def() {
		_ = Fea::parse("", &mut Lexer::new("anchorDef 300 0 ANCHOR_1;")).unwrap();
		_ = Fea::parse("", &mut Lexer::new("anchorDef 120 -20 contourpoint 5 ANCHOR_2;")).unwrap();
	}
	#[test]
	fn group_seq() {
		_ = Class::parse(&mut Lexer::new("endash emdash figuredash]")).unwrap();
		_ = Class::parse(&mut Lexer::new(r#"\0-\31]"#)).unwrap();
		_ = Class::parse(&mut Lexer::new("A-Z]")).unwrap();
		_ = Class::parse(&mut Lexer::new("A.swash - Z.swash]")).unwrap();
		_ = Class::parse(&mut Lexer::new("a - z]")).unwrap();
		_ = Class::parse(&mut Lexer::new("ampersand.01 - ampersand.58]")).unwrap();
		_ = Class::parse(&mut Lexer::new("ampersand.1 - ampersand.58] ")).unwrap();
		// group
		_ = Class::parse(&mut Lexer::new("@Vowels.lc @Vowels.uc y Y]")).unwrap();
		_ = Class::parse(&mut Lexer::new("A.oldstyle - Z.oldstyle ampersand.oldstyle  @smallCaps]")).unwrap();
	}
	#[test]
	fn group_def() {
		_ = Fea::parse("", &mut Lexer::new("@Vowels.lc = [a e i o u];")).unwrap();
		_ = Fea::parse("", &mut Lexer::new("@Vowels = [@Vowels.lc @Vowels.uc y Y];")).unwrap();
		_ = Fea::parse("", &mut Lexer::new("@Figures_lining_tabular = @FIGSDEFAULT;")).unwrap();
		let content = "@Vowels =[A.oldstyle - Z.oldstyle ampersand.oldstyle  @smallCaps];";
		_ = Fea::parse("", &mut Lexer::new(content)).unwrap();
	}
}
